/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.constant.CommonConstant;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.domain.IsfdModelManagementRendering;
import com.comac.ins.isfd.domain.bo.IsfdModelManagementRenderingBo;
import com.comac.ins.isfd.domain.bo.query.IsfdModelManagementRenderingQueryBo;
import com.comac.ins.isfd.domain.vo.*;
import com.comac.ins.isfd.mapper.IsfdModelManagementRenderingMapper;
import com.comac.ins.isfd.rpc.isfd.bo.IsfdModelSaveBo;
import com.comac.ins.isfd.service.IIsfdModelManagementPartService;
import com.comac.ins.isfd.service.IIsfdModelManagementRenderingTaskService;
import com.comac.ins.isfd.service.IIsfdModelManagementStructureDefinitionTreeService;
import com.comac.ins.isfd.service.IIsfdModelManagementTaskService;
import com.comac.ins.system.service.ISysDictDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.comac.ins.isfd.util.CreateGltfFromBDF.createGltfFromBDF;

/**
 * 模型零件渲染Service业务层处理
 *
 * @author Lion Li
 * @date 2024-08-30
 */
@RequiredArgsConstructor
@Service
public class IsfdModelManagementRenderingTaskServiceImpl implements IIsfdModelManagementRenderingTaskService {

    @Autowired
    private final IsfdModelManagementRenderingMapper baseMapper;

    @Autowired
    protected IIsfdModelManagementPartService isfdModelManagementPartService;

    @Autowired
    protected IIsfdModelManagementTaskService isfdModelManagementTaskService;

    @Autowired
    private ISysDictDataService iSysDictDataService;

    @Autowired
    private IIsfdModelManagementStructureDefinitionTreeService iIsfdModelManagementStructureDefinitionTreeService;

    /**
     * 查询模型零件渲染
     *
     * @param id 主键
     * @return 模型零件渲染
     */
    @Override
    public IsfdModelManagementRenderingVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询模型零件渲染列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 模型零件渲染分页列表
     */
    @Override
    public TableDataInfo<IsfdModelManagementRenderingVo> queryPageList(IsfdModelManagementRenderingBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<IsfdModelManagementRendering> lqw = buildQueryWrapper(bo);
        Page<IsfdModelManagementRenderingVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的模型零件渲染列表
     *
     * @param bo 查询条件
     * @return 模型零件渲染列表
     */
    @Override
    public List<IsfdModelManagementRenderingVo> queryList(IsfdModelManagementRenderingBo bo) {
        LambdaQueryWrapper<IsfdModelManagementRendering> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IsfdModelManagementRendering> buildQueryWrapper(IsfdModelManagementRenderingBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IsfdModelManagementRendering> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getPartName()), IsfdModelManagementRendering::getPartName, bo.getPartName());
        lqw.eq(StringUtils.isNotBlank(bo.getParsedBdfPath()), IsfdModelManagementRendering::getParsedBdfPath, bo.getParsedBdfPath());
        lqw.eq(StringUtils.isNotBlank(bo.getGltfPath()), IsfdModelManagementRendering::getGltfPath, bo.getGltfPath());
        lqw.eq(StringUtils.isNotBlank(bo.getIndexPath()), IsfdModelManagementRendering::getIndexPath, bo.getIndexPath());
        lqw.eq(StringUtils.isNotBlank(bo.getMaterialLibraryPath()), IsfdModelManagementRendering::getMaterialLibraryPath, bo.getMaterialLibraryPath());
        lqw.eq(StringUtils.isNotBlank(bo.getCloudAddress()), IsfdModelManagementRendering::getCloudAddress, bo.getCloudAddress());
        lqw.eq(bo.getIsValid() != null, IsfdModelManagementRendering::getIsValid, bo.getIsValid());
        return lqw;
    }

    /**
     * 查询唯一符合条件的模型零件渲染数据
     *
     * @param businessId, type 查询条件
     * @return 模型零件渲染单条数据
     */
    @Override
    public IsfdModelManagementRenderingVo queryUniqueOne(Long businessId, String type) {
        return baseMapper.selectVoOne(new LambdaQueryWrapper<IsfdModelManagementRendering>()
            .eq(businessId != null, IsfdModelManagementRendering::getBusinessId, businessId)
            .eq(StringUtils.isNotBlank(type), IsfdModelManagementRendering::getType, type));
    }

    /**
     * 新增模型零件渲染
     *
     * @param bo 模型零件渲染
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(IsfdModelManagementRenderingBo bo) {
        return Boolean.TRUE;
    }

    /**
     * 加载模型零件渲染
     *
     * @param bo 模型零件渲染
     * @return gltf文件及xref文件
     */
    @Override
    public IsfdModelManagementRenderingResultVo loadTask(IsfdModelManagementRenderingQueryBo bo) {
        // 根据任务id查询文件位置
        Long businessId = bo.getBusinessId();
        String type = bo.getType();
        String partName = "";
        IsfdModelManagementTaskVo isfdModelManagementTaskVo = isfdModelManagementTaskService.queryById(businessId);
        IsfdModelManagementRenderingVo isfdModelManagementTaskRenderingVo = this.queryUniqueOne(businessId, type);

        if (isfdModelManagementTaskVo == null) {
            // 如果零件库内没有，但渲染库内查到，删掉
            if (isfdModelManagementTaskRenderingVo != null) {
                baseMapper.deleteById(isfdModelManagementTaskRenderingVo.getId());
            }
            throw new BaseException("任务不存在，任务编号：" + businessId + "，没有查询到相关数据，请确认数据后重试！");
        }

        // 获取文件保存路径前缀
        String taskRenderPrefix = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
            CommonConstant.MODEL_MANAGEMENT_TASK_RENDER_PREFIX);
        if (StringUtils.isBlank(taskRenderPrefix)) {
            throw new BaseException("字典中没有找到文件存储地址的相关配置。");
        }
        // 新增零件渲染数据
        if (isfdModelManagementTaskRenderingVo == null) {

            // 生成文件
            String[] paths = generateFiles(isfdModelManagementTaskVo, taskRenderPrefix);


            // 落表
            IsfdModelManagementRendering isfdModelManagementRendering = new IsfdModelManagementRendering();
            isfdModelManagementRendering.setBusinessId(businessId);
            isfdModelManagementRendering.setType(type);
            isfdModelManagementRendering.setPartName(partName);
            isfdModelManagementRendering.setParsedBdfPath(paths[0]);
            isfdModelManagementRendering.setGltfPath(paths[1]);
            isfdModelManagementRendering.setItemXrefPath(paths[2]);
            isfdModelManagementRendering.setMaterialLibraryPath(paths[3]);
            isfdModelManagementRendering.setIndexPath(paths[4]);
            baseMapper.insert(isfdModelManagementRendering);
            isfdModelManagementTaskRenderingVo = this.queryUniqueOne(businessId, type);
        }

        // 如果vo的渲染文件存储路径与现在的不一样，也重新生成文件
        String renderingPath = isfdModelManagementTaskRenderingVo.getRenderingPath();
        if (taskRenderPrefix.equals(renderingPath) == Boolean.FALSE) {
            // 生成文件
            String[] paths = generateFiles(isfdModelManagementTaskVo, taskRenderPrefix);
            // 更新vo
            isfdModelManagementTaskRenderingVo.setRenderingPath(taskRenderPrefix);
            isfdModelManagementTaskRenderingVo.setParsedBdfPath(paths[0]);
            isfdModelManagementTaskRenderingVo.setGltfPath(paths[1]);
            isfdModelManagementTaskRenderingVo.setItemXrefPath(paths[2]);
            isfdModelManagementTaskRenderingVo.setMaterialLibraryPath(paths[3]);
            isfdModelManagementTaskRenderingVo.setIndexPath(paths[4]);
            IsfdModelManagementRendering isfdModelManagementRendering = MapstructUtils.convert(isfdModelManagementTaskRenderingVo, IsfdModelManagementRendering.class);
            baseMapper.updateById(isfdModelManagementRendering);
        }

        // 获取vo里的存储路径
        String gltfPath = isfdModelManagementTaskRenderingVo.getGltfPath();
        String xrefPath = isfdModelManagementTaskRenderingVo.getItemXrefPath();
        String binPath = this.replaceExtension(gltfPath, ".bin");

        // 如果文件为空，也重新生成
        if (new File(xrefPath).exists() == Boolean.FALSE) {
            generateFiles(isfdModelManagementTaskVo, taskRenderPrefix);
        }

        // 返回vo实体
        IsfdModelManagementRenderingResultVo isfdModelManagementRenderingResultVo = new IsfdModelManagementRenderingResultVo();
        isfdModelManagementRenderingResultVo.setGltfPath(gltfPath);
        isfdModelManagementRenderingResultVo.setXrefPath(xrefPath);
        isfdModelManagementRenderingResultVo.setBinPath(binPath);

        return isfdModelManagementRenderingResultVo;
    }


    private String[] generateFiles(IsfdModelManagementTaskVo isfdModelManagementTaskVo,
                                   String taskRenderPrefix) {

        // 批次编号
        String batchNumber = isfdModelManagementTaskVo.getBatchNumber();

        // 新增零件渲染数据
        String materialPath = iSysDictDataService.selectDictValueByTypeAndLabel(CommonConstant.SYS_COMMON_DICT_TYPE,
            CommonConstant.MODEL_MANAGEMENT_MATERIAL_PATH);

        String bdfPath = isfdModelManagementTaskVo.getIndexFilePath();
        String businessIdString = isfdModelManagementTaskVo.getId().toString();

        // 根据bdf文件路径生成gltf，xref文件路径
        String parsedBdfPath = batchNumber + File.separator + businessIdString + File.separator + businessIdString + "_parsed_bdf" + ".json";
        String gltfPath = batchNumber + File.separator + businessIdString + File.separator + businessIdString + ".gltf";
        String xrefPath = batchNumber + File.separator + businessIdString + File.separator + businessIdString + "_xref" + ".json";
        // 获取完整路径
        String bdfFullPath = bdfPath;
        String materialFullPath = materialPath;
        String gltfFullPath = taskRenderPrefix + gltfPath;
        String xrefFullPath = taskRenderPrefix + xrefPath;
        String parsedBdfFullPath = taskRenderPrefix + parsedBdfPath;

        // 解析bdf
        Map parsingResult = createGltfFromBDF(bdfFullPath, materialFullPath, parsedBdfFullPath, gltfFullPath, xrefFullPath);
        System.out.println(parsingResult);

        return new String[]{parsedBdfFullPath, gltfFullPath, xrefFullPath, materialFullPath, bdfFullPath};
    }

    private String replaceExtension(String filePath, String newExtension) {
        int dotIndex = filePath.lastIndexOf('.');
        if (dotIndex != -1) {
            return filePath.substring(0, dotIndex) + newExtension;
        } else {
            return filePath + newExtension;
        }
    }


    /**
     * 修改模型零件渲染
     *
     * @param bo 模型零件渲染
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(IsfdModelManagementRenderingBo bo) {
        IsfdModelManagementRendering update = MapstructUtils.convert(bo, IsfdModelManagementRendering.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IsfdModelManagementRendering entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除模型零件渲染信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public IsfdModelManagementRenderingResultVo thirdPartyLoadTask(Long id) {
        IsfdModelManagementTaskVo taskVo = isfdModelManagementTaskService.queryById(id);
        if (taskVo == null) {
            throw new BaseException("模型组装不存在，请确认后重试！");
        }
        String url = taskVo.getUrl();
        if (StringUtils.isBlank(url)) {
            throw new BaseException("模型组装未生成渲染的zip包，请确认后重试！");
        }
        String modelNumber = taskVo.getModelNumber();
        String batchNumber = taskVo.getBatchNumber();
        List<IsfdModelManagementPartVo> isfdModelManagementPartVoList = isfdModelManagementTaskService.getPartListByTaskId(id);
        IsfdModelManagementStructureDefinitionTreeVo modelVo = iIsfdModelManagementStructureDefinitionTreeService.queryOneByQueryIndex(modelNumber, null, null);
        IsfdModelManagementStructureDefinitionTreeVo batchVo = iIsfdModelManagementStructureDefinitionTreeService.queryOneByQueryIndex(modelNumber, batchNumber, null);
        Map<String, String> sectionMaps = new HashMap<>();
        for (IsfdModelManagementPartVo partVo : isfdModelManagementPartVoList) {
            String sectionNumber = partVo.getSectionNumber();
            if (StringUtils.isBlank(sectionMaps.get(sectionNumber))) {
                IsfdModelManagementStructureDefinitionTreeVo sectionVo = iIsfdModelManagementStructureDefinitionTreeService.queryOneByQueryIndex(modelNumber, batchNumber, sectionNumber);
                sectionMaps.put(sectionNumber, sectionVo.getName());
            }
        }
        IsfdModelSaveBo isfdModelSaveBo = new IsfdModelSaveBo();
        isfdModelSaveBo.setUrl(url);
        isfdModelSaveBo.setModelNumber(modelNumber);
        isfdModelSaveBo.setModelName(modelVo.getName());
        isfdModelSaveBo.setBatchNumber(batchNumber);
        isfdModelSaveBo.setBatchName(batchVo.getName());
        isfdModelSaveBo.setSections(sectionMaps);
        isfdModelSaveBo.setTaskName(taskVo.getTaskName());
        isfdModelSaveBo.setMoldName(taskVo.getMoldName());
        // todo 调用第三方团队接口获取renderUrl
        String renderUrl = "";

        IsfdModelManagementRenderingResultVo result = new IsfdModelManagementRenderingResultVo();
        result.setRenderUrl(renderUrl);
        return result;
    }
}
